#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : error_handler.py
@DESCRIPTION   : 全局错误和异常处理中间件
'''
from flask import jsonify, render_template, request
from flask_login import current_user
import traceback
import functools

from app.common.error_codes import ErrorCode
from app.common.logutil import log, log_error

class BusinessError(Exception):
    """业务逻辑错误
        初始化参数: 
            message_or_result: dict 或者 消息, 例如：
            {
                'success': False,
                'code': '10000',
                'message': '错误消息',
                'data': None
            }
    """
    def __init__(self, message_or_result, code=None, data=None):
        if isinstance(message_or_result, dict):
            # 使用字典初始化
            self.success = message_or_result.get('success', False)
            self.message = message_or_result.get('message', '未知错误')
            self.code = message_or_result.get('code', ErrorCode.UNKNOWN_ERROR)
            self.data = message_or_result.get('data', data)
        else:
            # 使用独立参数初始化
            self.success = False
            self.message = str(message_or_result)
            self.code = code or ErrorCode.UNKNOWN_ERROR
            self.data = data
            
        super().__init__(self.message)

def get_current_user():
    """
    获取当前用户
    """
    if hasattr(current_user, 'is_authenticated') and current_user.is_authenticated:
        return f"用户ID: {current_user.user_id}, 用户名: {current_user.loginname}-{current_user.nickname}"
    
    return "无登录用户"

# 服务层统一异常处理装饰器
def service_exception(f):
    """
    服务层统一异常处理装饰器
    
    使用方式:
    @service_exception_handler
    def some_service_method(params):
        # 业务逻辑
        if error_condition:
            raise BusinessError("错误消息", ErrorCode.SOME_ERROR)
        # 成功返回
        return ErrorCode.success_response(data=result)
    """
    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        _user = get_current_user()  # 移到这里，每次请求时获取当前用户

        try:
            return f(*args, **kwargs)
        except BusinessError as e:
            # 处理业务逻辑异常
            log_error(f"服务层业务异常: {e.code}-{e.message}::: {_user}", e) # 记录警告日志
            return ErrorCode.error_response(e.code, e.message)
        except Exception as e:
            # 处理系统异常
            log_error(f"服务层异常::: {_user}", e)
            return ErrorCode.error_response(ErrorCode.UNKNOWN_ERROR, f"系统错误: {str(e)}")
    return decorated_function

# 路由层统一异常处理装饰器
def route_exceptions(f):
    """
    视图函数的异常处理装饰器
    自动捕获视图函数中的异常，并根据异常类型返回适当的响应
    """
    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        _user = get_current_user()  # 移到这里，每次请求时获取当前用户
        try:
            return f(*args, **kwargs)
        except BusinessError as e:
            # 业务逻辑错误
            if request.path.startswith('/api/'):
                return jsonify({
                    'success': False,
                    'code': e.code,
                    'message': e.message
                }), 400
            # 记录业务错误日志
            log_error(f"路由层抛出业务异常: {e.code}-{e.message}::: {_user}", e)

            return render_template('errors/business_error.html', error=e), e.code
        
        except Exception as e:
            # 技术错误 (如数据库错误、内部服务错误等)
            log_error(f"路由层抛出技术错误异常::{_user} - 技术错误, 视图函数异常:", e)
            
            if request.path.startswith('/api/'):
                return jsonify({
                    'success': False,
                    'code': 500,
                    'message': '服务器内部错误'
                }), 500

            return render_template('errors/500.html'), 500
        
    return decorated_function

def init_error_handler(app):
    """
    初始化全局错误和异常处理
    """
    # 404 错误处理
    @app.errorhandler(404)
    def page_not_found(e):
        # API请求返回JSON
        if request.path.startswith('/api/'):
            return jsonify({
                'success': False, 
                'code': 404, 
                'message': '请求的资源不存在'
            }), 404
        # 网页请求返回HTML
        return render_template('errors/404.html'), 404
    
    # 500 服务器内部错误处理
    @app.errorhandler(500)
    def internal_server_error(e):
        # 记录详细错误信息到日志
        log_error(f"500 错误: {str(e)}\n{traceback.format_exc()}")
        
        # API请求返回JSON
        if request.path.startswith('/api/'):
            return jsonify({
                'success': False, 
                'code': 500, 
                'message': '服务器内部错误'
            }), 500
        # 网页请求返回HTML
        return render_template('errors/500.html'), 500
    
    # 403 禁止访问错误处理
    @app.errorhandler(403)
    def forbidden(e):
        log_error(f"403 错误: {str(e)}")
        if request.path.startswith('/api/'):
            return jsonify({
                'success': False, 
                'code': 403, 
                'message': '没有权限访问该资源'
            }), 403
        return render_template('errors/403.html'), 403
    
    # 处理未捕获的异常
    @app.errorhandler(Exception)
    def handle_unexpected_error(e):
        log_error(f"未捕获异常: {str(e)}\n{traceback.format_exc()}")
        
        if request.path.startswith('/api/'):
            return jsonify({
                'success': False, 
                'code': 500, 
                'message': f'服务器异常: {str(e)}'
            }), 500
        return render_template('errors/500.html'), 500
    
    # 在错误处理中间件中添加业务处理异常
    @app.errorhandler(BusinessError)
    def handle_business_error(e):
        if request.path.startswith('/api/'):
            return jsonify({
                'success': False, 
                'code': e.code, 
                'message': e.message
            }), 400
        
        return render_template('errors/business_error.html', error=e), 400